/*
 * acooly.cn Inc.
 * Copyright (c) 2016 All Rights Reserved.
 * create by zhangpu
 * date:2016年3月20日
 *
 */
package com.ouwen.smartpay.service.notify;

import com.fm.common.order.NotifyOrder;
import com.fm.core.utils.ShutdownHooks;
import com.fm.core.utils.Strings;
import com.ouwen.smartpay.entity.NotifyDetail;
import com.ouwen.smartpay.entity.NotifyMessage;
import com.ouwen.smartpay.entity.OrderInfo;
import com.ouwen.smartpay.openapi.order.NotifyOrderItem;
import com.ouwen.smartpay.service.NotifyDetailService;
import com.ouwen.smartpay.service.NotifyMessageSendDispatcher;
import com.ouwen.smartpay.service.NotifyMessageSendService;
import com.ouwen.smartpay.service.NotifyMessageService;
import com.ouwen.smartpay.utils.BeanUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/***
 *@author <a href="http://youngitman.tech">青年IT男</a>
 *@version v1.0.0
 *@className NotifyMessageSendServiceImpl
 *@description 消息发送
 *@JunitTest: {@link  }
 *@date 16:13 2020-04-27
 *
 **/
@Service("notifyMessageSendService")
public class NotifyMessageSendServiceImpl implements NotifyMessageSendService, InitializingBean {

    private static final Logger logger = LoggerFactory.getLogger(NotifyMessageSendServiceImpl.class);

    @Resource
    protected NotifyMessageSendDispatcher notifyMessageSendDispatcher;

    @Resource
    protected NotifyMessageService notifyMessageService;

    @Resource
    private NotifyDetailService notifyDetailService;

    private ScheduledExecutorService retryService;

    @Override
    public void doNotifyMessage(final NotifyOrder notifyOrder, final OrderInfo orderInfo) {

        try {

            //保存异步通知信息
            NotifyMessage notifyMessage = notifyMessageService.saveNotifyMessageAndUpdateOrderInfo(notifyOrder, orderInfo);

            //执行异步通知
            notifyMessageSendDispatcher.dispatch(notifyMessage, notifyOrder);

        } catch (Exception e) {

            throw new RuntimeException("发送异步通知失败:" + e.getMessage());

        }
    }


    /***
     *
     * 获取消息异步通知
     *
     * @author liyong
     * @date 1:46 PM 2020/4/29
     * @param
     * @exception
     * @return void
     **/
    @Override
    public void autoNotifyMessage() {

        try {

            List<NotifyMessage> notifyMessages = notifyMessageService.listUnProcessed(5);

            if (notifyMessages == null || notifyMessages.isEmpty()) {

                logger.debug("异步通知 无可发消息...");

                return;
            }
            for (NotifyMessage notifyMessage : notifyMessages) {

                NotifyDetail notifyDetail = notifyDetailService.findOrderDetailNotifyInfoByOrderId(notifyMessage.getId());

                String content = notifyDetail.getNotifyInfo();

                try {
                    if (Strings.isNotBlank(content)) {

                        NotifyOrder notifyOrder = new NotifyOrder();

                        NotifyOrderItem notifyOrderItem = new NotifyOrderItem();

                        BeanUtil.transMap2Bean(BeanUtil.jsonToMap(content), notifyOrderItem);

                        notifyOrder.setTranStatus(notifyOrderItem.getTranStatus());

                        notifyOrder.setTranDesc(notifyOrderItem.getTranDesc());

                        notifyOrder.setTranDate(notifyOrderItem.getTranDate());

                        notifyOrder.setMerchOrderNo(notifyOrderItem.getMerchOrderNo());

                        notifyOrder.setPartnerId(notifyMessage.getPartnerId());

                        notifyOrder.setSubPartnerId(notifyMessage.getSubPartnerId());

                        notifyOrder.setGid(notifyMessage.getGid());

                        notifyOrder.setDescription(notifyOrderItem.getDescription());

                        notifyOrder.setRespCode(notifyOrderItem.getRespCode());

                        notifyOrder.setRespMsg(notifyOrderItem.getRespMsg());

                        notifyMessageSendDispatcher.dispatch(notifyMessage, notifyOrder);

                    } else {

                        logger.error("定时任务异步通知内容不能为空,消息内容:{}", notifyMessage);
                    }
                } catch (Exception e) {

                    logger.error("定时任务异步通知内容转换实体异常:{}", e);
                }
            }

            logger.info("异步通知任务分发:{}条消息，内容:{}", notifyMessages.size(), notifyMessages);

        } catch (Exception e) {

            logger.warn("异步通知任务失败:{}", e.getMessage());
        }
    }

    /***
     *
     * 定时任务获取需要通知的消息
     *
     * @author liyong
     * @date 1:47 PM 2020/4/29
     * @param
     * @exception
     * @return void
     **/
    private void autoNotifyMessageAtFixRate() {

        if (retryService == null) {

            retryService = Executors.newScheduledThreadPool(1, r -> {

                Thread thread = new Thread(r);

                thread.setName("NOTIFY-MESSAGE-RETRY-TASK");

                thread.setDaemon(true);
                return thread;
            });

            ShutdownHooks.addShutdownHook(() -> retryService.shutdown(), "notifyMessageShutdownHook");

            //启动后1分钟开始执行,间隔1分钟执行一次
            retryService.scheduleAtFixedRate(
                    () -> this.autoNotifyMessage(), 60, 1 * 60, TimeUnit.SECONDS);
        }
    }

    @Override
    public void afterPropertiesSet() {
        try {

            autoNotifyMessageAtFixRate();

        } catch (Exception e) {

            logger.error("The retry notify  task init failed", e);
        }
    }
}
